package com.wm.machine.baselibrary.utils;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.AnimRes;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityOptionsCompat;

import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;

/**
 * Copyright app 的攻击类
 * Activity 栈管理
 * author chengxp
 * date 2018/3/1
 * describe
 * history
 */

public class AppUtils {

  private static final int TWO = 2;

  @SuppressLint("StaticFieldLeak")
  private static Application mApplication;
  private static WeakReference<Activity> mTopActivityWeakRef;
  private static List<Activity> mActivityList = new LinkedList<>();

  public AppUtils() {
    throw new UnsupportedOperationException("DensityUtils cannot be instantiated");
  }

  /**
   * 初始化AppUtis
   *
   * @param application 应用
   */
  public static void init(@NonNull final Application application) {
    mApplication = application;
    application.registerActivityLifecycleCallbacks(mCallbacks);
  }

  /**
   * 获取 Application 实例
   *
   * @return Application
   */
  public static Application getApplication() {
    if (mApplication != null) {
      return mApplication;
    }
    throw new NullPointerException("u should init first");
  }

  /**
   * 获取栈顶的Activity 的弱引用
   * 
   * @return WeakReference
   */
  public WeakReference<Activity> getTopActivityWeakRef() {
    return mTopActivityWeakRef;
  }

  /**
   * 设置栈顶的activity的弱引用
   *
   * @param activity activity对象
   */
  private static void setTopActivityWeakRef(final Activity activity) {
    if (activity.getClass() == PermissionUtils.PermissionActivity.class) {
      return;
    }
    if (mTopActivityWeakRef == null || !activity.equals(mTopActivityWeakRef.get())) {
      mTopActivityWeakRef = new WeakReference<>(activity);
    }
  }

  /**
   * 获取 ActivityLifecycleCallbacks
   *
   * @return ActivityLifecycleCallbacks
   */
  public static Application.ActivityLifecycleCallbacks getmCallbacks() {
    return mCallbacks;
  }

  /**
   * 设置 ActivityLifecycleCallbacks
   *
   * @param mCallbacks 需要设置的ActivityLifecycleCallbacks
   */
  public static void setmCallbacks(Application.ActivityLifecycleCallbacks mCallbacks) {
    AppUtils.mCallbacks = mCallbacks;
  }

  /**
   * 获取任务栈中顶部的activity的弱引用
   *
   * @return WeakReference
   */
  public WeakReference<Activity> getWeakReference() {
    return mTopActivityWeakRef;
  }

  /**
   * 获取任务栈中activity的集合
   *
   * @return 集合list
   */
  public static List<Activity> getActivityList() {
    return mActivityList;
  }

  private static Application.ActivityLifecycleCallbacks mCallbacks =
      new Application.ActivityLifecycleCallbacks() {
        @Override
        public void onActivityCreated(Activity activity, Bundle bundle) {
          mActivityList.add(activity);
          setTopActivityWeakRef(activity);
        }

        @Override
        public void onActivityStarted(Activity activity) {
          setTopActivityWeakRef(activity);
        }

        @Override
        public void onActivityResumed(Activity activity) {
          setTopActivityWeakRef(activity);
        }

        @Override
        public void onActivityPaused(Activity activity) {

      }

        @Override
        public void onActivityStopped(Activity activity) {

      }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle bundle) {

      }

        @Override
        public void onActivityDestroyed(Activity activity) {
          mActivityList.remove(activity);
        }
      };


  /**
   * 判断 Activity 是否存在
   *
   * @param packageName 包名
   * @param className activity 全路径类名
   * @return {@code true}: 是<br>
   *         {@code false}: 否
   */
  public static boolean isActivityExists(@NonNull final String packageName,
      @NonNull final String className) {
    Intent intent = new Intent();
    intent.setClassName(packageName, className);
    return !(mApplication.getPackageManager().resolveActivity(intent, 0) == null
        || intent.resolveActivity(mApplication.getPackageManager()) == null
        || mApplication.getPackageManager().queryIntentActivities(intent, 0).size() == 0);
  }

  /**
   * 判断 Activity 是否存在栈中
   *
   * @param activity activity
   * @return {@code true}: 存在<br>
   *         {@code false}: 不存在
   */
  public static boolean isActivityExistsInStack(@NonNull final Activity activity) {
    for (Activity aActivity : mActivityList) {
      if (aActivity.equals(activity)) {
        return true;
      }
    }
    return false;
  }

  /**
   * 获取栈顶 Activity
   *
   * @return 栈顶 Activity
   */
  public static Activity getTopActivity() {
    if (mTopActivityWeakRef != null) {
      Activity activity = mTopActivityWeakRef.get();
      if (activity != null) {
        return activity;
      }
    }
    int size = mActivityList.size();
    return size > 0 ? mActivityList.get(size - 1) : null;
  }

  /**
   * 获取启动项 Activity
   *
   * @return 启动项 Activity
   */
  public static String getLauncherActivity() {
    return getLauncherActivity(mApplication.getPackageName());
  }

  /**
   * 获取启动项 Activity
   *
   * @param packageName 包名
   * @return 启动项 Activity
   */
  public static String getLauncherActivity(@NonNull final String packageName) {
    Intent intent = new Intent(Intent.ACTION_MAIN, null);
    intent.addCategory(Intent.CATEGORY_LAUNCHER);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    PackageManager pm = mApplication.getPackageManager();
    List<ResolveInfo> info = pm.queryIntentActivities(intent, 0);
    for (ResolveInfo aInfo : info) {
      if (aInfo.activityInfo.packageName.equals(packageName)) {
        return aInfo.activityInfo.name;
      }
    }
    return "no " + packageName;
  }

  /**
   * 获取上下文对象
   *
   * @return 上下文对象
   */
  private static Context getActivityOrApplication() {
    Activity topActivity = getTopActivity();
    return topActivity == null ? mApplication : topActivity;
  }

  /**
   * 启动 Activity
   *
   * @param intent 意图
   */
  public static void startActivity(@NonNull final Intent intent) {
    startActivity(intent, getActivityOrApplication(), null);
  }

  /**
   * 启动 Activity
   *
   * @param intent 意图
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void startActivity(@NonNull final Intent intent,
      @AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {
    Context context = getActivityOrApplication();
    startActivity(intent, context, getOptionsBundle(context, enterAnim, exitAnim));
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
      ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
    }
  }

  /**
   * 启动 Activity
   *
   * @param clz Activity 类
   */
  public static void startActivity(@NonNull final Class<?> clz) {
    Context context = getActivityOrApplication();
    startActivity(context, null, context.getPackageName(), clz.getName(), null);
  }

  /**
   * 启动 Activity
   *
   * @param clz Activity 类
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void startActivity(@NonNull final Class<?> clz,
      @AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {
    Context context = getActivityOrApplication();
    startActivity(context, null, context.getPackageName(), clz.getName(),
        getOptionsBundle(context, enterAnim, exitAnim));
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
      ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
    }
  }

  /**
   * 启动 Activity
   *
   * @param activity activity
   * @param clz Activity 类
   */
  public static void startActivity(@NonNull final Activity activity,
      @NonNull final Class<?> clz) {
    startActivity(activity, null, activity.getPackageName(), clz.getName(), null);
  }


  /**
   * 启动 Activity
   *
   * @param activity activity
   * @param clz Activity 类
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void startActivity(@NonNull final Activity activity,
      @NonNull final Class<?> clz,
      @AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {

    startActivity(activity, null, activity.getPackageName(), clz.getName(),
        getOptionsBundle(activity, enterAnim, exitAnim));
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
      activity.overridePendingTransition(enterAnim, exitAnim);
    }
  }

  /**
   * 启动 Activity
   *
   * @param pkg 包名
   * @param cls 全类名
   */
  public static void startActivity(@NonNull final String pkg,
      @NonNull final String cls) {
    startActivity(getActivityOrApplication(), null, pkg, cls, null);
  }

  /**
   * 启动 Activity
   *
   * @param pkg 包名
   * @param cls 全类名
   * @param options 动画
   */
  public static void startActivity(@NonNull final String pkg,
      @NonNull final String cls,
      @NonNull final Bundle options) {
    startActivity(getActivityOrApplication(), null, pkg, cls, options);
  }

  /**
   * 启动 Activity
   *
   * @param pkg 包名
   * @param cls 全类名
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void startActivity(@NonNull final String pkg,
      @NonNull final String cls,
      @AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {
    Context context = getActivityOrApplication();
    startActivity(context, null, pkg, cls, getOptionsBundle(context, enterAnim, exitAnim));
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN && context instanceof Activity) {
      ((Activity) context).overridePendingTransition(enterAnim, exitAnim);
    }
  }

  /**
   * 启动指定的activity
   *
   * @param context 上下文
   * @param extras bundle 对象
   * @param pkg 包名
   * @param cls 类名
   * @param options 启动参数
   */
  private static void startActivity(final Context context, final Bundle extras, final String pkg,
      final String cls, final Bundle options) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    if (extras != null) {
      intent.putExtras(extras);
    }
    intent.setComponent(new ComponentName(pkg, cls));
    startActivity(intent, context, options);
  }

  /**
   * 启动activity
   *
   * @param intent intent对象
   * @param context 上下文
   * @param options 启动参数
   */
  private static void startActivity(final Intent intent, final Context context,
      final Bundle options) {
    if (!(context instanceof Activity)) {
      intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    }
    if (options != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
      context.startActivity(intent, options);
    } else {
      context.startActivity(intent);
    }
  }

  /**
   * 结束 Activity
   *
   * @param activity activity
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void finishActivity(@NonNull final Activity activity,
      @AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {
    activity.finish();
    activity.overridePendingTransition(enterAnim, exitAnim);
  }

  /**
   * 结束所有 Activity
   *
   * @param isLoadAnim 是否启动动画
   */
  public static void finishAllActivities(final boolean isLoadAnim) {
    for (int i = mActivityList.size() - 1; i >= 0; --i) {
      // 从栈顶开始移除
      Activity activity = mActivityList.get(i);
      // 在 onActivityDestroyed 发生 remove
      activity.finish();
      if (!isLoadAnim) {
        activity.overridePendingTransition(0, 0);
      }
    }
  }

  /**
   * 结束所有 Activity
   *
   * @param enterAnim 入场动画
   * @param exitAnim 出场动画
   */
  public static void finishAllActivities(@AnimRes final int enterAnim,
      @AnimRes final int exitAnim) {
    for (int i = mActivityList.size() - 1; i >= 0; --i) {
      // 从栈顶开始移除
      Activity activity = mActivityList.get(i);
      // 在 onActivityDestroyed 发生 remove
      activity.finish();
      activity.overridePendingTransition(enterAnim, exitAnim);
    }
  }

  /**
   * 结束除最新之外的所有 Activity
   *
   * @param isLoadAnim 是否启动动画
   */
  public static void finishAllActivitiesExceptNewest(final boolean isLoadAnim) {
    for (int i = mActivityList.size() - TWO; i >= 0; i--) {
      mActivityList.get(i).finish();
    }
  }

  /**
   * 自定义进场退场动画
   *
   * @param context context
   * @param enterAnim 进场动画资源id
   * @param exitAnim 退场动画资源id
   * @return Bundle 对象
   */
  private static Bundle getOptionsBundle(final Context context, final int enterAnim,
      final int exitAnim) {
    return ActivityOptionsCompat.makeCustomAnimation(context, enterAnim, exitAnim).toBundle();
  }

}
